package com.android.accessibility.function;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.widget.Toast;

import com.android.accessibility.PhoneManager;
import com.android.accessibility.service.QQObserverService;
import com.android.accessibility.stat.Stat;
import com.android.accessibility.utils.AuthHelper;
import com.android.accessibility.utils.Log;
import com.android.accessibility.utils.SDUtils;
import com.android.accessibility.utils.Utils;

public class QQOnekeyforwardingVideo {

    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private int mMask = FileObserver.CREATE | FileObserver.CLOSE_WRITE
            | FileObserver.DELETE | FileObserver.ALL_EVENTS;
    private List<FileObserver> mObserverList;
    private List<String> mObservePath = null;

    private static final String FORWARD_VIDEO_EXT = ".mp4";
    private static final String FORWARD_VIDEO_THUMB_EXT = ".jpg";

    private static final String RECORD_VIDEO_EXT = ".mp4";
    private static final String RECORD_VIDEO_THUMB_EXT = ".mp4.thumb";

    private String mForwradVideo;
    private String mForwradVideoThumb;

    private String mRecordVideo;
    private String mRecordVideoThumb;

    private Context mContext;

    public QQOnekeyforwardingVideo(Context context) {
        mContext = context;
    }

    /**
     * 通过系统api获取监控路径
     */
    private void getObserverPathByApi() {
        Log.d(Log.TAG, "");
        File externalDir = Environment.getExternalStorageDirectory();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("external", Build.MODEL + " -- " + (externalDir != null ? externalDir.getAbsolutePath() : "null"));
        // Stat.get(mContext).reportKVEvent("onekeyforward", params);
        File qqChatDir = null;
        if (externalDir != null) {
            qqChatDir = new File(externalDir, "tencent/MobileQQ/shortvideo");
        }
        if (qqChatDir != null) {
            mObservePath = Utils.getRecursiveFolder(qqChatDir.getAbsolutePath());
        }
    }

    private void getObserverPathByCmd() {
        Log.d(Log.TAG, "");
        List<String> sdList = SDUtils.getAllSdcardPath();
        if (sdList == null || sdList.size() <= 0) {
            return;
        }

        Map<String, Object> params = new HashMap<String, Object>();
        String out = Build.MODEL + " -- ";
        for (String s : sdList) {
            out += s + "|";
        }
        params.put("external", out);
        // Stat.get(mContext).reportKVEvent("onekeyforward", params);

        List<String> list = null;
        for (String s : sdList) {
            list = Utils.getRecursiveFolder(new File(s, "tencent/MobileQQ/shortvideo").getAbsolutePath());
            if (list != null && list.size() > 0) {
                if (mObservePath == null) {
                    mObservePath = new ArrayList<String>();
                }
                mObservePath.addAll(list);
            }
        }
    }

    private void findForwardVideo(int event, String path) {
        if (event == FileObserver.CREATE) {
            if (path.toLowerCase().endsWith(FORWARD_VIDEO_EXT)) {
                mForwradVideo = path;
            } else if (path.toLowerCase().endsWith(FORWARD_VIDEO_THUMB_EXT)) {
                mForwradVideoThumb = path;
            }
        }
    }

    private void findRecordVideo(int event, String path) {
        if (TextUtils.isEmpty(mForwradVideo)
                || TextUtils.isEmpty(mForwradVideoThumb)) {
            return;
        }
        if (event == FileObserver.CLOSE_WRITE) {
            if (path.toLowerCase().endsWith(RECORD_VIDEO_EXT)) {
                mRecordVideo = path;
            } else if (path.toLowerCase().endsWith(RECORD_VIDEO_THUMB_EXT)) {
                mRecordVideoThumb = path;
            }
            if (!TextUtils.isEmpty(mRecordVideo)
                    && !TextUtils.isEmpty(mRecordVideoThumb)) {
                processRecordVideo();
            }
        }
    }

    private void processRecordVideo() {
        processRecordVideoLocked();
    }

    private void showToast(final String toast) {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void processRecordVideoLocked() {
        Log.d(Log.TAG, "mForwradVideo      : " + mForwradVideo);
        Log.d(Log.TAG, "mForwradVideoThumb : " + mForwradVideoThumb + "\n");
        Log.d(Log.TAG, "mRecordVideo       : " + mRecordVideo);
        Log.d(Log.TAG, "mRecordVideoThumb  : " + mRecordVideoThumb + "\n");

        AuthHelper.checkForceStop(mContext, true);
        boolean forceStop = PreferenceManager.getDefaultSharedPreferences(
                mContext).getBoolean("forcestop", false);
        if (forceStop) {
            Log.d(Log.TAG, "forcestop");
            Intent intent = new Intent(mContext, QQObserverService.class);
            mContext.stopService(intent);
            Map<String, Object> params = new HashMap<String, Object>();
            String hashCode = PhoneManager.get(mContext).getAndroidIDHashCode();
            params.put("forcestop", Build.MODEL + " -- " + hashCode);
            Stat.get(mContext).reportKVEvent("onekeyforward", params);
            return;
        }

        File forwardVideo = new File(mForwradVideo);
        File forwardVideoThumb = new File(mForwradVideoThumb);
        File recordVideo = new File(mRecordVideo);
        File recordVideoThumb = new File(mRecordVideoThumb);
        boolean r1 = false;
        boolean r2 = false;
        boolean r3 = false;
        boolean r4 = false;
        if (recordVideo.exists()) {
            r1 = recordVideo.delete();
            if (recordVideo.exists()) {
                r1 = deleteFileSafely(recordVideo);
            }
        }
        if (recordVideoThumb.exists()) {
            r2 = recordVideoThumb.delete();
            if (recordVideoThumb.exists()) {
                r2 = deleteFileSafely(recordVideoThumb);
            }
        }
        r3 = forwardVideo.renameTo(recordVideo);
        r4 = forwardVideoThumb.renameTo(recordVideoThumb);

        boolean keepOldVideo = PreferenceManager.getDefaultSharedPreferences(
                mContext).getBoolean("keep_oldvideo", false);
        if (keepOldVideo) {
            Utils.copyFile(recordVideoThumb.getAbsolutePath(), forwardVideoThumb.getAbsolutePath());
            Utils.copyFile(recordVideo.getAbsolutePath(), forwardVideo.getAbsolutePath());
        }
        mForwradVideo = null;
        mForwradVideoThumb = null;
        mRecordVideo = null;
        mRecordVideoThumb = null;
        Map<String, Object> params = new HashMap<String, Object>();
        String hashCode = PhoneManager.get(mContext).getAndroidIDHashCode();
        params.put("forward", Build.MODEL + " -- " + hashCode + " |" + r1 + "|" + r2 + "|" + r3 + "|" + r4);
        Stat.get(mContext).reportKVEvent("onekeyforward", params);
        if(r1 && r2 && r3 && r4) {
            showToast("转发视频已经替换，请点击发送");
            params = new HashMap<String, Object>();
            hashCode = PhoneManager.get(mContext).getAndroidIDHashCode();
            params.put("forwarddetail", hashCode + " -- " + sdf.format(new Date()));
            Stat.get(mContext).reportKVEvent("onekeyforward", params);
        }
    }

    /**
     * 安全删除文件.
     * @param file
     * @return
     */
    public static boolean deleteFileSafely(File file) {
        try {
            if (file != null) {
                String tmpPath = file.getParent() + File.separator
                        + System.currentTimeMillis();
                File tmp = new File(tmpPath);
                file.renameTo(tmp);
                return tmp.delete();
            }
        } catch (Exception e) {
            Log.d(Log.TAG, "error : " + e);
        }
        return false;
    }

    public void startOnekeyForward() {
        getObserverPathByApi();
        if (mObservePath == null || mObservePath.size() <= 0) {
            getObserverPathByCmd();
        }
        if (mObservePath == null || mObservePath.size() <= 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            String hashCode = PhoneManager.get(mContext).getAndroidIDHashCode();
            params.put("emptyobserver", Build.MODEL + " -- " + hashCode);
            Stat.get(mContext).reportKVEvent("onekeyforward", params);
            return;
        }

        mObserverList = new ArrayList<FileObserver>();
        for (String path : mObservePath) {
            mObserverList.add(startObserver(path));
        }
    }

    private void saveObserverPath(String observerPath) {
        SharedPreferences p = PreferenceManager
                .getDefaultSharedPreferences(mContext);
        p.edit().putString("observer_path", observerPath).commit();
    }

    private String getObserverPath() {
        SharedPreferences p = PreferenceManager
                .getDefaultSharedPreferences(mContext);
        return p.getString("observer_path", null);
    }

    private FileObserver startObserver(final String observerPath) {
        Log.d(Log.TAG, "path : " + observerPath);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("observer_path", Build.MODEL + " -- " + observerPath);
        Stat.get(mContext).reportKVEvent("onekeyforward", params);
        FileObserver observer = new FileObserver(observerPath, mMask) {
            @Override
            public void onEvent(int event, String path) {
                saveObserverPath(observerPath);
                Log.d(Log.TAG, "path : " + new File(observerPath, path));
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("onevent", Build.MODEL + " -- " + event);
                // Stat.get(mContext).reportKVEvent("observer", params);
                if (!path.startsWith("tempvideo")) {
                    findForwardVideo(event,
                            new File(observerPath, path).getAbsolutePath());
                }
                if (path.startsWith("tempvideo")) {
                    findRecordVideo(event,
                            new File(observerPath, path).getAbsolutePath());
                }
            }
        };
        observer.startWatching();
        return observer;
    }

    public void stopOnekeyForward() {
        Log.d(Log.TAG, "");
        if (mObserverList == null) {
            return;
        }
        for (FileObserver o : mObserverList) {
            stopObserver(o);
        }
    }

    private void stopObserver(FileObserver observer) {
        if (observer != null) {
            observer.stopWatching();
        }
    }

    public void copyVideoToWechatAndgenerateThumb(Context context,
            String filePath) {
        String path = getObserverPath();
        if (TextUtils.isEmpty(path)) {
            Toast.makeText(context, "请先使用一键转发功能", Toast.LENGTH_SHORT).show();
            return;
        }
        String localName = "1111111111111111111111111111";
        String newPath = new File(path, localName + ".mp4").getAbsolutePath();
        Log.d(Log.TAG, "newPath : " + newPath);
        Utils.copyFile(filePath, newPath);
        generateVideoThumbnail(localName, filePath);
    }

    public void generateVideoThumbnail(String fileName, String filePath) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            File file = new File(getObserverPath(), fileName + ".jpg");
            if (file != null && !file.exists()) {
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            retriever.setDataSource(filePath);
            bitmap = retriever.getFrameAtTime();
            bitmap.compress(CompressFormat.JPEG, 80, fos);
            fos.close();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
    }
}
